﻿using System.Collections.Generic;
using System.Linq;
using System.Configuration;
using System.IO;
using Citi.Helpers;
using System.Diagnostics;
using System.Timers;
using System;

namespace Citi.Scheduler.ConsoleUi.RunnerApplication
{
    public class Program
    {
        private static string StartPath { get { return ConfigurationManager.AppSettings["StartPath"]; } }
        private static string StopPath { get { return ConfigurationManager.AppSettings["StopPath"]; } }
        private static string ExecutedPath { get { return ConfigurationManager.AppSettings["ExecutedPath"]; } }
        private static string NetworkUser { get { return ConfigurationManager.AppSettings["NetworkUser"]; } }
        private static string NetWorkPassword { get { return ConfigurationManager.AppSettings["NetWorkPassword"]; } }
        private static IEnumerable<string> ProcessesToKill { get { return ConfigurationManager.AppSettings["ProcessesToKill"].Split(';').ToList(); } }
        private static string ProcessName;
        private static bool UnlockLockMachine;

        private static int routineExecutionId;

        static void Main(string[] args)
        {
            timerStop.Elapsed += TimerStopOnElapsed;

            if (!Directory.Exists(StartPath))
                Directory.CreateDirectory(StartPath);

            if (!Directory.Exists(StopPath))
                Directory.CreateDirectory(StopPath);

            if (!Directory.Exists(ExecutedPath))
                Directory.CreateDirectory(ExecutedPath);

            StartProcess();
        }

        private static void UnlockMachine()
        {
            if (!UnlockLockMachine) return;

            System.Threading.Thread.Sleep(3000);

            var sharedLogon = @"\\gruvnascti0016.wlb.lac.nsroot.net\DATA_GRP1\FinTOOLS\Tools\Scheduler Runner\RunLogon.bat";
            var localLogon = @"C:\Temp\RunLogon.bat";

            if (!File.Exists(localLogon))
                File.Copy(sharedLogon, localLogon, true);

            var process = ExecuteProcess(localLogon);
            process.WaitForExit();

            System.Threading.Thread.Sleep(3000);
        }

        private static void LockMachine()
        {
            if (!UnlockLockMachine) return;

            System.Threading.Thread.Sleep(5000);

            var path = @"\\gruvnascti0016.wlb.lac.nsroot.net\DATA_GRP1\FinTOOLS\Tools\Scheduler Runner\LockWorkStation.exe";

            var process = ExecuteProcess(path);
            process.WaitForExit();
        }

        private static void StartProcess()
        {
            var fileStart = Directory.GetFiles(StartPath).OrderBy(File.GetCreationTime).FirstOrDefault();

            if (fileStart == null) return;

            routineExecutionId = int.Parse(Path.GetFileNameWithoutExtension(fileStart));
            var fileContent = File.ReadAllLines(fileStart);

            var processToExecute = fileContent[0];
            processToExecute = processToExecute.Replace("\"", string.Empty);
            ProcessName = Path.GetFileNameWithoutExtension(processToExecute);
            var arguments = fileContent.Count() > 1 ? fileContent[1] : null;

            UnlockLockMachine = fileContent.Count() > 2 && fileContent[2].ToLower() == "true" ? true : false;

            UnlockMachine();

            var executedFile = Path.Combine(ExecutedPath, Path.GetFileName(fileStart));

            if (File.Exists(executedFile))
                File.Delete(executedFile);

            File.Move(fileStart, executedFile);

            var process = ExecuteProcess(processToExecute, arguments);

            timerStop.Start();

            process.WaitForExit();

            KillAssociatedProcesses();
            LockMachine();
        }

        private static Process ExecuteProcess(string processToExecute, string arguments = null)
        {
            var processInfo = new ProcessStartInfo(processToExecute)
            {
                CreateNoWindow = false,
                WindowStyle = ProcessWindowStyle.Maximized,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                Arguments = arguments
            };

            return Process.Start(processInfo);
        }

        private static Timer timerStop = new Timer { Interval = 10000 };

        private static void TimerStopOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
        {
            try
            {
                var fileStop = Path.Combine(StopPath, string.Concat(routineExecutionId, ".txt"));

                if (!File.Exists(fileStop) && !Directory.GetFiles(StartPath).Any()) return;

                try
                {
                    timerStop.Stop();

                    File.Delete(fileStop);
                    var processes = Process.GetProcessesByName(ProcessName);

                    foreach (var process in processes)
                        process.Kill();
                }
                catch { }
                finally
                {
                    KillAssociatedProcesses();
                    LockMachine();
                    Environment.Exit(Environment.ExitCode);
                }
            }
            catch
            {
            }
        }

        private static void KillAssociatedProcesses()
        {
            foreach (var processToKill in ProcessesToKill)
            {
                var processes = Process.GetProcessesByName(processToKill);

                foreach (var process in processes)
                {
                    try
                    {
                        process.Kill();
                    }
                    catch { }
                }
            }
        }
    }
}
